package com.ksvip.next.components.util;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Random;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;

import lombok.extern.slf4j.Slf4j;


/**
 * 1.概述:在web项目中，服务端和前端经常需要交互数据，有的时候由于网络相应慢，客户端在提交某些敏感数据（比如按照正常的业务逻辑，此份数据只能保存一份）时
 * ，如果前端多次点击提交按钮会导致提交多份数据，这种情况我们是要防止发生的。 2.解决方法： ①前端处理：在提交之后通过js立即将按钮隐藏或者置为不可用。
 * ②后端处理：对于每次提交到后台的数据必须校验，也就是通过前端携带的令牌（一串唯一字符串）与后端校验来判断当前数据是否有效。
 * 3.总结：第一种方法相对来说比较简单，但是安全系数不高，第二种方法从根本上解决了问题，所以我推荐第二种方法 ---------------------
 * 作者：myjbase 来源：CSDN 原文：https://blog.csdn.net/myjbase/article/details/91869360
 * 版权声明：本文为博主原创文章，转载请附上博文链接！ Token的工具类
 */
public class TokenUtils {

    /**
     * 生成token放入session
     *
     * @param request
     * @param tokenServerkey
     */
    public static void createToken(final HttpServletRequest request, final String tokenServerkey) {
        final String token = TokenEnum.INSTANCE.makeToken();
        //单机可以使用，分布多台机器时应用redis处理
        request.getSession().setAttribute(tokenServerkey, token);
    }

    /**
     * 移除token
     *
     * @param request
     * @param tokenServerkey
     */
    public static void removeToken(final HttpServletRequest request, final String tokenServerkey) {
        request.getSession().removeAttribute(tokenServerkey);
    }

    /**
     * 判断请求参数中的token是否和session中一致
     *
     * @param request
     * @param tokenClientkey
     * @param tokenServerkey
     * @return
     */
    public static boolean judgeTokenIsEqual(final HttpServletRequest request, final String tokenClientkey,
                                            final String tokenServerkey) {
        final String token_client = request.getParameter(tokenClientkey);
        if (StringUtils.isEmpty(token_client)) {
            return false;
        }
        final String token_server = (String) request.getSession().getAttribute(tokenServerkey);
        if (StringUtils.isEmpty(token_server)) {
            return false;
        }

        if (!token_server.equals(token_client)) {
            return false;
        }

        return true;
    }

    @Slf4j
    public enum TokenEnum {
        INSTANCE;
        /**
         * 生成Token
         * @return
         */
        public String makeToken() {
            final String token = String.valueOf(System.currentTimeMillis() + new Random().nextInt(999999999));
            try {
                final MessageDigest md = MessageDigest.getInstance("md5");
                final byte[] md5 = md.digest(token.getBytes());
                return CodecUtils.base64Encode(md5);
            } catch (final NoSuchAlgorithmException e) {
                log.info("", e);
            }
            return null;
        }

    }

}
